From 999853b092c34a43383ae8b7b117820b79171c85 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Tue, 1 Apr 2008 10:06:58 +0100 Subject: [PATCH] xen: XSPolicy.can_run hypervisor support Add functionality for checking whether a domain is in a conflict set with existing domains. Signed-off-by: Stefan Berger --- xen/include/public/xsm/acm.h | 1 + xen/include/xsm/acm/acm_hooks.h | 14 ++++++++ xen/xsm/acm/acm_chinesewall_hooks.c | 36 +++++++++++++++++++ xen/xsm/acm/acm_policy.c | 3 ++ .../acm/acm_simple_type_enforcement_hooks.c | 2 ++ 5 files changed, 56 insertions(+) diff --git a/xen/include/public/xsm/acm.h b/xen/include/public/xsm/acm.h index 09e7879238..a66d399c6c 100644 --- a/xen/include/public/xsm/acm.h +++ b/xen/include/public/xsm/acm.h @@ -102,6 +102,7 @@ typedef uint32_t ssidref_t; #define ACMHOOK_none 0 #define ACMHOOK_sharing 1 #define ACMHOOK_authorization 2 +#define ACMHOOK_conflictset 3 /* -------security policy relevant type definitions-------- */ diff --git a/xen/include/xsm/acm/acm_hooks.h b/xen/include/xsm/acm/acm_hooks.h index 35ea144378..19e37f9e2e 100644 --- a/xen/include/xsm/acm/acm_hooks.h +++ b/xen/include/xsm/acm/acm_hooks.h @@ -116,6 +116,7 @@ struct acm_operations { ssidref_t ssidref2); int (*authorization) (ssidref_t ssidref1, ssidref_t ssidref2); + int (*conflictset) (ssidref_t ssidref1); /* determine whether the default policy is installed */ int (*is_default_policy) (void); }; @@ -151,6 +152,8 @@ static inline int acm_sharing(ssidref_t ssidref1, ssidref_t ssidref2) { return 0; } static inline int acm_authorization(ssidref_t ssidref1, ssidref_t ssidref2) { return 0; } +static inline int acm_conflictset(ssidref_t ssidref1) +{ return 0; } static inline int acm_domain_create(struct domain *d, ssidref_t ssidref) { return 0; } static inline void acm_domain_destroy(struct domain *d) @@ -329,6 +332,17 @@ static inline int acm_authorization(ssidref_t ssidref1, ssidref_t ssidref2) } +static inline int acm_conflictset(ssidref_t ssidref1) +{ + if ((acm_primary_ops->conflictset != NULL) && + acm_primary_ops->conflictset(ssidref1)) + return ACM_ACCESS_DENIED; + else if ((acm_secondary_ops->conflictset != NULL) && + acm_secondary_ops->conflictset(ssidref1)) + return ACM_ACCESS_DENIED; + return ACM_ACCESS_PERMITTED; +} + /* Return true iff buffer has an acm policy magic number. */ extern int acm_is_policy(char *buf, unsigned long len); diff --git a/xen/xsm/acm/acm_chinesewall_hooks.c b/xen/xsm/acm/acm_chinesewall_hooks.c index a6e2eb3949..65e60e7cb4 100644 --- a/xen/xsm/acm/acm_chinesewall_hooks.c +++ b/xen/xsm/acm/acm_chinesewall_hooks.c @@ -641,6 +641,41 @@ static int chwall_is_default_policy(void) (chwall_bin_pol.max_ssidrefs == 2 ) ); } + +static int chwall_is_in_conflictset(ssidref_t ssidref1) +{ + /* is ssidref1 in conflict with any running domains ? */ + int rc = 0; + int i, j; + ssidref_t ssid_chwall; + + read_lock(&acm_bin_pol_rwlock); + + ssid_chwall = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref1); + + if ( ssid_chwall >= 0 && ssid_chwall < chwall_bin_pol.max_ssidrefs ) { + for ( i = 0; i < chwall_bin_pol.max_conflictsets && rc == 0; i++ ) { + for ( j = 0; j < chwall_bin_pol.max_types; j++ ) { + if ( chwall_bin_pol.conflict_aggregate_set + [i * chwall_bin_pol.max_types + j] && + chwall_bin_pol.ssidrefs + [ssid_chwall * chwall_bin_pol.max_types + j]) + { + rc = 1; + break; + } + } + } + } else { + rc = 1; + } + + read_unlock(&acm_bin_pol_rwlock); + + return rc; +} + + struct acm_operations acm_chinesewall_ops = { /* policy management services */ .init_domain_ssid = chwall_init_domain_ssid, @@ -666,6 +701,7 @@ struct acm_operations acm_chinesewall_ops = { /* generic domain-requested decision hooks */ .sharing = NULL, .authorization = NULL, + .conflictset = chwall_is_in_conflictset, .is_default_policy = chwall_is_default_policy, }; diff --git a/xen/xsm/acm/acm_policy.c b/xen/xsm/acm/acm_policy.c index a7eff56903..3f66e8ae73 100644 --- a/xen/xsm/acm/acm_policy.c +++ b/xen/xsm/acm/acm_policy.c @@ -446,6 +446,9 @@ acm_get_decision(ssidref_t ssidref1, ssidref_t ssidref2, u32 hook) ret = acm_authorization(ssidref1, ssidref2); break; + case ACMHOOK_conflictset: + ret = acm_conflictset(ssidref1); + default: /* deny */ break; diff --git a/xen/xsm/acm/acm_simple_type_enforcement_hooks.c b/xen/xsm/acm/acm_simple_type_enforcement_hooks.c index d58c49fcd4..01eae51bb2 100644 --- a/xen/xsm/acm/acm_simple_type_enforcement_hooks.c +++ b/xen/xsm/acm/acm_simple_type_enforcement_hooks.c @@ -899,8 +899,10 @@ struct acm_operations acm_simple_type_enforcement_ops = { .fail_grant_map_ref = NULL, .pre_grant_setup = ste_pre_grant_setup, .fail_grant_setup = NULL, + /* generic domain-requested decision hooks */ .sharing = ste_sharing, .authorization = ste_authorization, + .conflictset = NULL, .is_default_policy = ste_is_default_policy, }; -- 2.30.2